﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Happy.Query.Filters.Configuration.Internal
{
    internal sealed class Config : IConfig, IConfigOfBeginGroup, IConfigOfFilter, IConfigOfConnector, IConfigOfEndGroup
    {
        private readonly Stack<StackItem> _stack = new Stack<StackItem>();
        private Connector _currentConnector = Filters.Connector.Empty;

        public IConfigOfBeginGroup BeginGroup()
        {
            _stack.Push(new StackItem
            {
                FilterGroupConnector = _currentConnector
            });

            _currentConnector = Filters.Connector.Empty;

            return this;
        }

        public IConfigOfConnector Not()
        {
            return this.Connector(Filters.Connector.Not);
        }

        public IConfigOfFilter Filter(string property, Operator @operator, params Operand[] operands)
        {
            var filter = new Filter(_currentConnector, property, @operator, operands);
            _stack.Peek().FilterGroupFilters.Add(filter);

            _currentConnector = Filters.Connector.Empty;

            return this;
        }

        public IConfigOfConnector Connector(Connector connector)
        {
            _currentConnector = connector;

            return this;
        }

        public IConfigOfEndGroup EndGroup()
        {
            if (_stack.Count <= 1)
            {
                return this;
            }

            var stackItem = _stack.Pop();
            var group = new FilterGroup(stackItem.FilterGroupConnector, stackItem.FilterGroupFilters.ToArray());
            _stack.Peek().FilterGroupFilters.Add(group);

            return this;
        }

        public FilterGroup Done()
        {
            var item = _stack.Pop();

            return new FilterGroup(item.FilterGroupConnector, item.FilterGroupFilters.ToArray());
        }

        private class StackItem
        {
            public StackItem()
            {
                this.FilterGroupFilters = new List<IFilter>();
            }

            public Connector FilterGroupConnector { get; set; }

            public List<IFilter> FilterGroupFilters { get; private set; }
        }
    }
}
